package com.example.zkviewer.service.impl;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.utils.ZKPaths;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Stat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import com.example.zkviewer.model.ZkNode;
import com.example.zkviewer.service.ZookeeperService;

@Service
public class ZookeeperServiceImpl implements ZookeeperService {

    private static final Logger logger = LoggerFactory.getLogger(ZookeeperServiceImpl.class);

    @Autowired
    private CuratorFramework curatorFramework;

    @Override
    public List<ZkNode> getChildren(String path) {
        try {
            List<String> childrenPaths = curatorFramework.getChildren().forPath(path);
            List<ZkNode> childrenNodes = new ArrayList<>();
            
            for (String childPath : childrenPaths) {
                String fullPath = ZKPaths.makePath(path, childPath);
                boolean isLeaf = curatorFramework.getChildren().forPath(fullPath).isEmpty();
                String data = null;
                try {
                    data = getData(fullPath);
                } catch (Exception e) {
                    logger.error("Error getting data for node {}", fullPath, e);
                }
                childrenNodes.add(new ZkNode(fullPath, data, isLeaf));
            }
            
            return childrenNodes;
        } catch (Exception e) {
            logger.error("Error getting children for path {}", path, e);
            return new ArrayList<>();
        }
    }

    @Override
    public ZkNode getNodeData(String path) {
        try {
            Stat stat = new Stat();
            byte[] dataBytes = curatorFramework.getData().storingStatIn(stat).forPath(path);
            String data = dataBytes != null ? new String(dataBytes) : "";
            boolean isLeaf = curatorFramework.getChildren().forPath(path).isEmpty();
            List<ACL> aclList = curatorFramework.getACL().forPath(path);
            String acl = aclList.toString();
            
            ZkNode node = new ZkNode(path, data, isLeaf);
            node.setAcl(acl);
            node.setCtime(stat.getCtime());
            node.setMtime(stat.getMtime());
            
            if (!isLeaf) {
                node.setChildren(getChildren(path));
            }
            
            return node;
        } catch (KeeperException.NoNodeException e) {
            logger.error("Node not found: {}", path, e);
            return null;
        } catch (Exception e) {
            logger.error("Error getting node data for path {}", path, e);
            return null;
        }
    }

    @Override
    public boolean createNode(String path, String data, boolean isEphemeral) {
        try {
            // 确保父节点存在
            createParentIfNotExists(path);
            
            CreateMode mode = isEphemeral ? CreateMode.EPHEMERAL : CreateMode.PERSISTENT;
            curatorFramework.create()
                    .creatingParentsIfNeeded()
                    .withMode(mode)
                    .forPath(path, data != null ? data.getBytes() : new byte[0]);
            logger.info("Node created successfully: {}", path);
            return true;
        } catch (KeeperException.NodeExistsException e) {
            logger.error("Node already exists: {}", path, e);
            return false;
        } catch (Exception e) {
            logger.error("Error creating node: {}", path, e);
            return false;
        }
    }

    @Override
    public boolean updateNode(String path, String data) {
        try {
            curatorFramework.setData().forPath(path, data != null ? data.getBytes() : new byte[0]);
            logger.info("Node updated successfully: {}", path);
            return true;
        } catch (KeeperException.NoNodeException e) {
            logger.error("Node not found: {}", path, e);
            return false;
        } catch (Exception e) {
            logger.error("Error updating node: {}", path, e);
            return false;
        }
    }

    @Override
    public boolean deleteNode(String path) {
        try {
            curatorFramework.delete().deletingChildrenIfNeeded().forPath(path);
            logger.info("Node deleted successfully: {}", path);
            return true;
        } catch (KeeperException.NoNodeException e) {
            logger.error("Node not found: {}", path, e);
            return false;
        } catch (Exception e) {
            logger.error("Error deleting node: {}", path, e);
            return false;
        }
    }

    @Override
    public boolean exists(String path) {
        try {
            Stat stat = curatorFramework.checkExists().forPath(path);
            return stat != null;
        } catch (Exception e) {
            logger.error("Error checking node existence: {}", path, e);
            return false;
        }
    }

    @Override
    public ZkNode getNodeTree(String path) {
        ZkNode node = getNodeData(path);
        if (node != null && !node.isLeaf()) {
            node.setChildren(getChildren(path));
        }
        return node;
    }
    
    @Override
    public boolean deleteNodes(List<String> paths) {
        if (paths == null || paths.isEmpty()) {
            logger.warn("No paths provided for batch deletion");
            return true;
        }
        
        int totalPaths = paths.size();
        int successfulDeletions = 0;
        
        for (String path : paths) {
            try {
                if (deleteNode(path)) {
                    successfulDeletions++;
                }
            } catch (Exception e) {
                logger.error("Error during batch deletion for path {}", path, e);
            }
        }
        
        logger.info("Batch deletion completed: {}/{}", successfulDeletions, totalPaths);
        
        // 返回是否所有节点都成功删除
        return successfulDeletions == totalPaths;
    }

    // 辅助方法：获取节点数据
    private String getData(String path) {
        try {
            byte[] data = curatorFramework.getData().forPath(path);
            return data != null ? new String(data) : "";
        } catch (Exception e) {
            logger.error("Error getting data for node {}", path, e);
            return "";
        }
    }

    // 辅助方法：递归创建父节点
    private void createParentIfNotExists(String path) {
        try {
            if (path.equals("/")) {
                return;
            }
            
            String parentPath = ZKPaths.getPathAndNode(path).getPath();
            if (!parentPath.isEmpty() && curatorFramework.checkExists().forPath(parentPath) == null) {
                createParentIfNotExists(parentPath);
                curatorFramework.create().creatingParentsIfNeeded().forPath(parentPath);
            }
        } catch (Exception e) {
            logger.error("Error creating parent node for {}", path, e);
        }
    }
}